/*
 * 	Flan.Zeng 2011-2016	http://git.oschina.net/signup?inviter=flan
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.flan.stock.utils;

import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;

import android.graphics.Bitmap;

/**
 * 网络图片的内存缓存对象
 * @author flan
 * @date   2015年11月12日
 */
public class MemoryCache {
	
	/**
	 * 放入缓存时是个同步操作
	 * LinkedHashMap构造方法的最后一个参数true代表这个map里的元素将按照最近使用次数由少到多排列，即LRU
	 * 这样的好处是如果要将缓存中的元素替换，则先遍历出最近最少使用的元素来替换以提高效率
	 */
	private Map<String, Bitmap> cache = Collections.synchronizedMap(new LinkedHashMap<String,Bitmap>(10,1.5f,true));
	/**
     *  缓存只能占用的最大堆内存
     */
	private long limit = 1024000;
	/**
	 *  缓存中图片所占用的字节，初始0，将通过此变量严格控制缓存所占用的堆内存
	 */
	private long size = 0;
	
	public MemoryCache() {
		super();
		
		//缓存最大值为 运行时内存的四分之一
		limit = Runtime.getRuntime().maxMemory()/4;
	}
	
	/**
	 * 根据图片URL 查找缓存中的图片
	 * @param imgUrl
	 * @return
	 */
	public Bitmap getBitmap(String imgUrl){
		
		try{
            if(!cache.containsKey(imgUrl)){
            	return null;
            }
            return cache.get(imgUrl);//NullPointerException sometimes happen here http://code.google.com/p/osmdroid/issues/detail?id=78 
        }catch(NullPointerException ex){
            ex.printStackTrace();
            return null;
        }
	}
	
	/**
	 * 将从网络上获取的Bitmap加入缓存中
	 * @param id
	 * @param bitmap
	 */
	public void put(String imgUrl,Bitmap bitmap){
		try {
			if(cache.containsKey(imgUrl)){
				size -= getBitmapSize(cache.get(imgUrl));
			}
			cache.put(imgUrl, bitmap);
			size += getBitmapSize(bitmap);
			checkCackeSize();
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 控制堆内存大小，超出最大值时按照LRU算法先替换掉最近最少使用的图片缓存
	 */
	private void checkCackeSize(){
		if(size > limit){
			
			Iterator<Entry<String, Bitmap>> iterator = cache.entrySet().iterator();
			while(iterator.hasNext()){
				Entry<String,Bitmap> entry = iterator.next();
				size -= getBitmapSize(entry.getValue());
				iterator.remove();
				if(size <= limit){
					break;
				}
			}
		}
	}
	
	/**
	 * 获取图片占用的内存
	 * @param bitmap
	 * @return bitmap的二进制大小
	 */
	private long getBitmapSize(Bitmap bitmap){
		if(bitmap != null){
			return bitmap.getRowBytes()*bitmap.getHeight();
		}
		return 0;
	}
	
	/**
	 * 清空缓存
	 */
	public void clear(){
		try{
            //NullPointerException sometimes happen here http://code.google.com/p/osmdroid/issues/detail?id=78 
            cache.clear();
            size=0;
        }catch(NullPointerException ex){
            ex.printStackTrace();
        }
	}
	
}


















